#pragma once
#include "Common.h"

#define STATEMENTS_DATA_SIZE 0x1000

enum PARSE_NODE_TYPE
{
	PNT_ASSIGN,
	PNT_ADD_ASSIGN,
	PNT_SUB_ASSIGN,
	PNT_MUL_ASSIGN,
	PNT_DIV_ASSIGN,

	PNT_ADD,
	PNT_SUB,
	PNT_MUL,
	PNT_DIV,

	PNT_GOTO,
	
	PNT_PRE_INCREMENT,
	PNT_POST_INCREMENT,
	PNT_PRE_DECREMENT,
	PNT_POST_DECREMENT,

	PNT_IDENTIFIER,
	PNT_TEMP_VAR,
	PNT_CONST
};

struct ParseNode
{
	enum PARSE_NODE_TYPE type;
};

// Sub classes of ParseNode

struct OneArgParseNode
{
	struct ParseNode* arg0;
};

struct TwoArgParseNode
{
	struct ParseNode* arg0;
	struct ParseNode* arg1;
};

#define GotoParseNode OneArgParseNode

#define PostIncrementParseNode OneArgParseNode
#define PreIncrementParseNode OneArgParseNode
#define PostDecrementParseNode OneArgParseNode
#define PreDecrementParseNode OneArgParseNode

#define MulParseNode TwoArgParseNode
#define DivParseNode TwoArgParseNode

#define AddParseNode TwoArgParseNode
#define SubParseNode TwoArgParseNode

#define AssignParseNode TwoArgParseNode
#define AddAssignParseNode TwoArgParseNode
#define SubAssignParseNode TwoArgParseNode
#define MulAssignParseNode TwoArgParseNode
#define DivAssignParseNode TwoArgParseNode

struct ConstParseNode
{
	struct Constant value;
};

struct IdentifierParseNode
{
	struct Symbol* identifier;
};

// This is never created in the bison file
struct TemporaryVariableParseNode
{
	struct Variable* variable;
};


/////////////////////////////////////////////////////////////////////////////
// Parse Node Macros

#define PN_ALLOC(DEST, PN_STRUCT)\
	DEST = malloc(sizeof(struct ParseNode) + sizeof(PN_STRUCT))

#define PN_SET_TYPE(PN, PNT)\
	((struct ParseNode*)(PN))->type = PNT

#define PSUB_PARSENODE(PN, PN_STRUCT)\
	((PN_STRUCT*)(((char*)(PN)) + sizeof(struct ParseNode)))

extern struct ParseNode* statementData[STATEMENTS_DATA_SIZE];
extern struct ParseNode** statements;